(function (Window) {
    Window.prototype.load = function (param) {
        var _param = param;
        var canvas = document.getElementById(_param.id);
        var context = canvas.getContext("2d");
        context.font = "bold 10px sans-serif";
        _param.context = context;
        _param.canvas = canvas;

        canvas.onmousemove = function () {
            moveCanvas(_param);
        };
        init(_param);

        var data = [2, 6, 8, 4];
        var kdata =
                [
                    {
                        "openingPrice": 10,
                        "closingPrice": 8,
                        "highestPrice": 15,
                        "lowestPrice": 3
                    },
                    {
                        "openingPrice": 8,
                        "closingPrice": 10,
                        "highestPrice": 15,
                        "lowestPrice": 4
                    },
                    {
                        "openingPrice": 8,
                        "closingPrice": 7,
                        "highestPrice": 10,
                        "lowestPrice": 5
                    },
                    {
                        "openingPrice": 8,
                        "closingPrice": 12,
                        "highestPrice": 20,
                        "lowestPrice": 6
                    }
                ];

//        drawKLine(_param.context, _param.top, kdata, 0);
//        drawLine(_param.context, _param.top, data, 0);
//        drawBar(context, option.bottom, data);
    };

    function moveCanvas(_param) {
        var x = this.event.clientX - _param.canvas.offsetLeft;
        if (x - _param.padding > 0 && _param.context.canvas.width - x > 20) {
            console.log(Math.round((x - _param.start) / _param.xunit));
        }
    }


    function init(_param) {
        var context = _param.context;
        var width = context.canvas.width;
        var height = context.canvas.height;
        var padding = _param.padding;
        var top = {"x": padding, "y": padding, "width": width - padding * 2, "height": (height - padding * 2) * 0.7};
        var bottom = {"x": padding, "y": padding + (height - padding * 2) * 0.7, "width": width - padding * 2, "height": (height - padding * 2) * 0.3};
        _param.top = top;
        _param.bottom = bottom;

        drawFrame(_param);
        drawXAxisText(_param);
        drawYAxisText(_param);
    }

    function drawFrame(_param) {
        var top = _param.top;
        var bottom = _param.bottom;
        var context = _param.context;
        context.save();
        context.beginPath();
        context.strokeStyle = "#666666";
        context.rect(top.x, top.y, top.width, top.height + bottom.height);
        context.moveTo(bottom.x, bottom.y);
        context.lineTo(bottom.x + bottom.width, bottom.y);
        context.stroke();
        context.restore();
    }


    function drawXAxisText(_param) {
        var context = _param.context;
        context.save();
        context.beginPath();
        context.lineWidth = 0.5;
        var date = _param.date;
        var len = date.length;
        var top = _param.top;
        var bottom = _param.bottom;
        if (_param.border) {
            _param.xunit = top.width / len;
            _param.start = top.x + _param.xunit / 2;
        } else {
            _param.xunit = top.width / (len - 1);
            _param.start = top.x;
        }

        var width = context.measureText(date[0]).width + 20;
        var size = Math.round(width / _param.xunit);
        context.textAlign = "center";
        context.textBaseline = "top";
        for (var i = 0; i < len; i++) {
            if (_param.format) {
                if (_param.format(date[i])) {
                    context.moveTo(_param.start + _param.xunit * i, top.y);
                    context.lineTo(_param.start + _param.xunit * i, bottom.y + bottom.height);
                    context.fillText(date[i], _param.start + _param.xunit * i, bottom.y + bottom.height);
                }
            } else {
                context.moveTo(_param.start + _param.xunit * i, top.y);
                context.lineTo(_param.start + _param.xunit * i, bottom.y + bottom.height);
                context.fillText(date[i], _param.start + _param.xunit * i, bottom.y + bottom.height);
                i += size;
            }
        }

        context.stroke();
        context.restore();
    }


    function drawYAxisText(_param) {
        var context = _param.context;
        context.save();
        context.beginPath();
        context.lineWidth = 0.5;
        var top = _param.top;
        var info = _param.info;
        var middle = _param.middle;
        var array = new Array;
        for (var i = 0, len = info.length; i < len; i++) {
            array = array.concat(info[i].data);
        }
        var max = array.max();
        var min = array.min();
        _param.region = getAxisRegion(max, middle, min);
        _param.yunit = top.height / _param.region.interval;
        if (middle) {
            context.textAlign = "left";
            context.textBaseline = "middle";
            context.moveTo(top.x, top.y + top.height / 2);
            context.lineTo(top.x + top.width, top.y + top.height / 2);
            context.fillText(middle, top.x + 5, top.y + top.height / 2);
        }
        context.textAlign = "left";
        context.textBaseline = "top";
        context.fillText(_param.region.max, top.x + 5, top.y);
        context.textAlign = "left";
        context.textBaseline = "bottom";
        context.fillText(_param.region.min, top.x + 5, top.y + top.height);
        context.stroke();
        context.restore();
    }



    function drawKLine(context, line, data, middle) {
        var points = computeKLineCoordinate(line, data, middle);
        context.save();
        context.lineWidth = 1;
        context.beginPath();
        for (var i = 0, len = points.length; i < len; i++) {
            context.moveTo(points[i].line.x, points[i].line.y);
            context.lineTo(points[i].line.x, points[i].line.y2);
            context.fillRect(points[i].bar.x, points[i].bar.y, points[i].bar.w, points[i].bar.h);
        }
        context.stroke();
        context.restore();
    }


    function drawLine(context, line, data, middle) {
        var points = computeLineCoordinate(line, data, middle);
        context.save();
        context.strokeStyle = "red";
        context.beginPath();
        for (var i = 0, len = points.length; i < len; i++) {
            context.lineTo(points[i].x, points[i].y);
        }
        context.stroke();
        context.restore();
    }

    function drawBar(context, bar, data) {
        var points = computeBarCoordinate(bar, data);
        context.save();
        context.fillStyle = "blue";
        for (var i = 0, len = points.length; i < len; i++) {
            context.fillRect(points[i].x, points[i].y, points[i].w, points[i].h);
        }
        context.restore();
    }

    function computeKLineCoordinate(region, data, middle) {
        var points = new Array;
        var yAxis = yAxisKLineRegion(data, middle);
        var len = data.length;
        var unit = region.width / (len);
        for (var i = 0; i < len; i++) {
            if (data[i]) {
                var max = data[i].openingPrice;
                var min = data[i].closingPrice;
                var color = 0;
                if (data[i].openingPrice < data[i].closingPrice) {
                    color = 1;
                    max = data[i].closingPrice;
                    min = data[i].openingPrice;
                }
                var line_x = unit * (i + 0.5) + region.x;
                var line_y = region.y + (1 - (data[i].highestPrice - yAxis.min) / yAxis.interval) * region.height;
                var line_y2 = region.y + (1 - (data[i].lowestPrice - yAxis.min) / yAxis.interval) * region.height;

                var bar_x = unit * i + region.x + 1;
                var bar_y = region.y + (1 - (max - yAxis.min) / yAxis.interval) * region.height;
                var bar_width = unit - 1;
                var bar_height = (max - min) / yAxis.interval * region.height;
                var line = {x: line_x, y: line_y, y2: line_y2, c: color};
                var bar = {x: bar_x, y: bar_y, w: bar_width, h: bar_height, c: color};
                points.push({line: line, bar: bar});
            }
        }
        return points;
    }

    function computeLineCoordinate(region, data, middle) {
        var points = new Array;
        var yAxis = yAxisRegion(data, middle);
        var len = data.length;
        var unit = region.width / (len - 1);
        for (var i = 0; i < len; i++) {
            if (!isNaN(data[i]) && data[i]) {
                var x = unit * i + region.x;
                var y = region.y + (1 - (data[i] - yAxis.min) / yAxis.interval) * region.height;
                points.push({x: x, y: y});
            }
        }
        return points;
    }

    function computeBarCoordinate(region, data) {
        var points = new Array;
        var max = data.max();
        var min = data.min();
        var len = data.length;
        var unit = region.width / (len - 1);
        for (var i = 0; i < len; i++) {
            if (!isNaN(data[i]) && data[i]) {
                var x = region.x + unit * (i - 0.5) + 1;
                var y = region.y + (1 - data[i] / max) * region.height;
                var width = unit - 1;
                var height = region.y - y + region.height;
                points.push({x: x, y: y, w: width, h: height});
            }
        }
        var startPoint = points[0];
        var endPoint = points[points.length - 1];
        startPoint.x = region.x + 1;
        startPoint.w = unit / 2 - 1;
        endPoint.w = unit / 2 - 1;
        return points;
    }

    function getAxisRegion(max, middle, min) {
        var interval = max - min;
        if (middle) {
            if (max - middle > middle - min) {
                min = middle * 2 - max;
                interval = (max - middle) * 2;
            } else {
                max = middle * 2 - min;
                interval = (middle - min) * 2;
            }
        }
        return {max: max, min: min, interval: interval};
    }


    function yAxisKLineRegion(data, middle) {
        var max = data[0].highestPrice;
        var min = data[0].lowestPrice;
        for (var i = 1, len = data.length; i < len; i++) {
            max = Math.max(max, data[i].highestPrice);
            min = Math.min(min, data[i].lowestPrice);
        }
        var interval = max - min;
        if (middle) {
            if (max - middle > middle - min) {
                min = middle * 2 - max;
                interval = (max - middle) * 2;
            } else {
                max = middle * 2 - min;
                interval = (middle - min) * 2;
            }
        }
        return {max: max, min: min, interval: interval};
    }

    function yAxisRegion(data, middle) {
        var max = data.max();
        var min = data.min();
        var interval = max - min;
        if (middle) {
            if (max - middle > middle - min) {
                min = middle * 2 - max;
                interval = (max - middle) * 2;
            } else {
                max = middle * 2 - min;
                interval = (middle - min) * 2;
            }
        }
        return {max: max, min: min, interval: interval};
    }

    Array.prototype.max = function () {
        var array = this.join(",").split(",");
        return Math.max.apply(this, array);
    };

    Array.prototype.min = function () {
        var array = this.join(",").split(",");
        return Math.min.apply(this, array);
    };


})(Window);

function initDate() {
    var len = 0;
    var date = new Array;
    for (var i = 9; i < 15; i++) {
        for (var j = 0; j < 60; j++) {
            if (!(i === 9 && j < 30 || i === 11 && j >= 30 || i === 12)) {
                if (i === 13 && j === 00) {
                    date[len++] = "11:30/13:00";
                } else {
                    var hours = i;
                    var minutes = j < 10 ? "0" + j : j;
                    date[len++] = hours + ":" + minutes;
                }
            }
        }
    }
    date[len] = "15:00";
    return date;
}

//var axisData = initDate();
var axisData = [1, 2, 3, 4, 5];
var lineData = [24, 34, 23, 12, 28];
var barData = [20, 44, 45, 32, 15];
var klineData = [[20, 26, 28, 18], [22, 18, 25, 12], [26, 28, 30, 22], [25, 22, 28, 20], [18, 12, 30, 18]];



var formatAxis = function (value) {
    if (value === "9:30" || value === "11:30/13:00" || value === "15:00") {
        return true;
    } else {
        return false;
    }
};


var param =
        {
            id: "map",
            date: axisData,
            middle: 25,
            border: true,
            padding: 20,
            info:
                    [
                        {
                            type: "line",
                            color: "red",
                            data: lineData
                        },
                        {
                            type: "bar",
                            data: barData
                        },
                        {
                            type: "kline",
                            data: klineData
                        }
                    ]
        }

load(param);